package com.atguigu.exam.service.impl;


import com.atguigu.exam.entity.*;
import com.atguigu.exam.exception.ExamException;
import com.atguigu.exam.mapper.ExamRecordMapper;
import com.atguigu.exam.mapper.PaperMapper;
import com.atguigu.exam.mapper.PaperQuestionMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.PaperQuestionService;
import com.atguigu.exam.service.PaperService;
import com.atguigu.exam.vo.PaperVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 试卷服务实现类
 */
@Slf4j
@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper> implements PaperService {

    @Autowired
    private PaperQuestionMapper paperQuestionMapper;
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private PaperQuestionService paperQuestionService;
    @Autowired
    private ExamRecordMapper examRecordMapper;


    @Override
    public Paper getPaperDetailsById(Integer id) {
        //调用自带的方法查询试卷信息
        Paper paper = baseMapper.selectById(id);
        //        //根据试卷id查询中间表获取PaperQuestion列表u
//        List<PaperQuestion> paperQuestions = paperQuestionMapper.selectList(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getPaperId, id));
//        //获取所有的题目id
//        List<Long> questionIds = paperQuestions.stream().map(PaperQuestion::getQuestionId).collect(Collectors.toList());
//        //创建一个保存所有题目的集合
//        List<Question> questionList = new ArrayList<>();
//        //遍历所有的题目id，查询题目信息
//        questionIds.forEach(questionId -> {
//            //根据问题id查询题目详情
//            Question questionDetailsById = questionMapper.getQuestionDetailsById(questionId);
//            //将题目信息添加到集合中
//            questionList.add(questionDetailsById);
//        });

        //调用questionMapper中根据试卷id查询试卷中所有题目的方法
        //questionMapper.getQuestionListByPaperId(id);


        List<Question> questionList = questionMapper.getQuestionListByPaperId(id);
        //排序
        //questionList.sort((o1, o2) -> o1.getType().compareTo(o2.getType()));
        questionList.sort(Comparator.comparing(Question::getType));
        //将所有的题目设置到试卷中
        paper.setQuestions(questionList);
        return paper;
    }


    @Override
    public Paper createPaper(PaperVo paperVo) {
        //判断是否已存在同名的试卷
        boolean exists = baseMapper.exists(new LambdaQueryWrapper<Paper>().eq(Paper::getName, paperVo.getName()));
        if (exists) {
            //已存在同名的试卷
            throw new ExamException(1002, "试卷名称已存在，请修改试卷名称");
        }
        //创建一个Paper对象
        Paper paper = new Paper();
        //复制相同的属性值
        BeanUtils.copyProperties(paperVo, paper);
        //设置试卷状态为草稿
        paper.setStatus("DRAFT");
        //获取paperVo中的map
        Map<Long, BigDecimal> questions = paperVo.getQuestions();
        //给试卷设置题目数量
        paper.setQuestionCount(questions.size());
        //计算试卷总分
        //reduce是 Stream 的终端操作，用于将流中所有元素聚合为一个结果
        //第一个参数BigDecimal.ZERO：表示累加的初始值（即从 0 开始累加）。
        //第二个参数BigDecimal::add：是一个BinaryOperator函数，这里引用了BigDecimal的add方法，
        // 用于将流中的每个元素与当前累加结果相加（等价于(sum, element) -> sum.add(element)）。
        BigDecimal totalScore = questions.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        //设置试卷总分
        paper.setTotalScore(totalScore);
        baseMapper.insert(paper);


        //将Map<Integer, BigDecimal>中的转换为List<PaperQuestion>
        List<PaperQuestion> paperQuestionList =
                questions.entrySet().stream()
                        .map(entry -> new PaperQuestion(paper.getId(), entry.getKey(), entry.getValue()))
                        .collect(Collectors.toList());
        //调用PaperQuestionService中的批量保存方法
        paperQuestionService.saveBatch(paperQuestionList);
        return paper;
    }


    @Override
    public Paper updatePaper(Integer id, PaperVo paperVo) {
        //已经是发布状态的试卷不能被修改
        Paper paper = baseMapper.selectById(id);
        if ("PUBLISHED".equals(paper.getStatus())) {
            //抛出异常
            throw new ExamException(1003, "发布状态的试卷不能被修改");
        }
        //判断是否已存在同名的试卷
        boolean exists =
                baseMapper.exists(new LambdaQueryWrapper<Paper>()
                        .eq(Paper::getName, paperVo.getName())
                        .ne(Paper::getId, id));//不等于某个 id
        if (exists) {
            //抛出异常
            throw new ExamException(1004, "试卷名称已存在，请修改试卷名称");
        }
        //复制属性值
        BeanUtils.copyProperties(paperVo, paper);
        //设置更新时间为当前日期
        paper.setUpdateTime(new Date());
        //获取paperVo中的map
        Map<Long, BigDecimal> questions = paperVo.getQuestions();
        //给试卷设置题目数量
        paper.setQuestionCount(questions.size());
        //计算试卷总分
        BigDecimal totalScore = questions.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        //设置试卷总分
        paper.setTotalScore(totalScore);
        //调用自带的根据id更新的方法
        baseMapper.updateById(paper);

        //操作中间表
        //根据试卷id删除中间表中的数据
        paperQuestionMapper.delete(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getPaperId, id));
        //将Map<Integer, BigDecimal>中的转换为List<PaperQuestion>
        List<PaperQuestion> paperQuestionList =
                questions.entrySet().stream().map(entry -> new PaperQuestion(paper.getId(), entry.getKey(), entry.getValue())).collect(Collectors.toList());
        //调用PaperQuestionService中的批量保存方法
        paperQuestionService.saveBatch(paperQuestionList);
        return paper;
    }

    @Override
    public void deletePaperById(Integer id) {
        //并且试卷正在被考试，不能删除
        Long count = examRecordMapper.selectCount(new LambdaQueryWrapper<ExamRecord>().eq(ExamRecord::getExamId, id).eq(ExamRecord::getStatus, "进行中"));
        if (count > 0) {
            //抛出异常
            throw new ExamException(1005, "试卷正在被考试，不能删除");
        }
        //调用自带的方法删除试卷
        baseMapper.deleteById(id);
        //删除中间表中的数据
        paperQuestionMapper.delete(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getPaperId, id));
    }

    @Override
    public void updatePaperStatus(Integer id, String status) {
        //并且试卷正在被考试，则不能更新状态
        Long count = examRecordMapper.selectCount(new LambdaQueryWrapper<ExamRecord>().eq(ExamRecord::getExamId, id).eq(ExamRecord::getStatus, "进行中"));
        if (count > 0) {
            //抛出异常
            throw new ExamException(1005, "试卷正在被考试，不能更新为草稿状态");
        }
        //调用带条件更新的方法
        baseMapper.update(null, new LambdaUpdateWrapper<Paper>().eq(Paper::getId, id).set(Paper::getStatus, status));
    }


    //BigDecimal测试
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.01");
        BigDecimal b = new BigDecimal("0.09");
        //a+b
        BigDecimal add = a.add(b);
        double dValue = add.doubleValue();
        System.out.println("dValue = " + dValue);
    }
}